#include "game_lite.h"
#include <unistd.h>
#include <cmath>
#include <iostream>

using namespace lumi;
using namespace std;

GameLite::GameLite()
    : right_answer_(0)
    , remain_question_number_(5)
{ }

void GameLite::init(WeakPtr<Loop> wp_loop)
{
    wp_loop_ = wp_loop;
    LoopSptr sp_loop = wp_loop.lock();

    sp_30sec_timer_ = sp_loop->newTimerEvent();
    sp_20sec_timer_ = sp_loop->newTimerEvent();
    sp_10sec_timer_ = sp_loop->newTimerEvent();
    sp_stdin_read_ev_ = sp_loop->newFdEvent();

    sp_30sec_timer_->initialize(time_interval::Second(30), Event::kOneshotMode);
    sp_30sec_timer_->setCallback(MakeFunction(&GameLite::on30SecReach, this));

    sp_20sec_timer_->initialize(time_interval::Second(20), Event::kOneshotMode);
    sp_20sec_timer_->setCallback(MakeFunction(&GameLite::on20SecReach, this));

    sp_10sec_timer_->initialize(time_interval::Second(10), Event::kOneshotMode);
    sp_10sec_timer_->setCallback(MakeFunction(&GameLite::on10SecReach, this));

    sp_stdin_read_ev_->initialize(STDIN_FILENO, FdEvent::kReadEvent, Event::kPersistMode);
    sp_stdin_read_ev_->setCallback(MakeFunction(&GameLite::onStdinReadable, this, _1));

    cout << "Welcome to Calculate GameLite." << endl
         << "You need answer 5 questions in 30 second. Each question has only 10 second." << endl
         << "Here we go!" << endl;

    srand(time(NULL));
    sp_stdin_read_ev_->enable();
    sp_30sec_timer_->enable();
    sp_20sec_timer_->enable();

    askQuestion();
}

void GameLite::askQuestion()
{
    sp_10sec_timer_->disable();

    int a = random() % 100;
    int b = random() % 100;
    right_answer_ = a + b;
    cout << a << " + " << b << " = ? " << endl << "your answer: " << flush;

    --remain_question_number_;
    sp_10sec_timer_->enable();
}

void GameLite::on30SecReach()
{
    cout << endl << "time is up, you fail!" << endl;
    LoopSptr sp_loop = wp_loop_.lock();
    sp_loop->exitLoop(time_interval::Zero());
}

void GameLite::on20SecReach()
{
    cout << endl << "10 sec remain ..." << endl;
}

void GameLite::on10SecReach()
{
    cout << endl << "timeout. You fail!" << endl;
    LoopSptr sp_loop = wp_loop_.lock();
    sp_loop->exitLoop(time_interval::Zero());
}

void GameLite::onStdinReadable(short event)
{
    char input_buff[200];
    int rsize = read(STDIN_FILENO, input_buff, sizeof(input_buff));
    input_buff[rsize - 1] = '\0';

    int answer = atoi(input_buff);
    if (answer == right_answer_) {
        if (remain_question_number_ == 0) {
            cout << "Congratulation! You win." << endl;

            LoopSptr sp_loop = wp_loop_.lock();
            sp_loop->exitLoop(time_interval::Zero());

        } else {
            askQuestion();
        }
    } else {
        cout << "wrong answer. You fail!" << endl;
        LoopSptr sp_loop = wp_loop_.lock();
        sp_loop->exitLoop(time_interval::Zero());
    }
}
